#include "revolutionSurface.h"

using namespace std;

RevolutionSurface::RevolutionSurface(int slices): Surface(slices+1,0)	
{
	// Los stacks estan determinados por los puntos de la curva.
}

RevolutionSurface::RevolutionSurface(const char* texturePath,int slices)
	:Surface(texturePath,slices+1,0)
{

}


RevolutionSurface::~RevolutionSurface()
{
	m_curvePoints.DeleteAll();
}

void RevolutionSurface::Update(float dt,const Curve& curve)	
{
	//Borro todo y agrego de nuevo con lo que tiene la curva.
	m_curvePoints.DeleteAll();

	const vector<Point3D*>& points = curve.GetCurvePoints();
	vector<Point3D*>::const_iterator it = points.begin();

	for(it; it < points.end(); it++)
	{
		m_curvePoints.push_back(new Point3D(*(*it)));
	}

	Surface::Update(dt);
}

void RevolutionSurface::loadIndexArray()
{
	unsigned int currStack = 0;
	unsigned int currSlice = 0;
	unsigned int i[4];

	m_stacks = m_curvePoints.size();

	// Si puedo formar quads.
	if (m_vertices.size() > 3)
	{
		for(currStack = 0; currStack <  m_stacks - 1; currStack++)
		{
			for(currSlice = 0; currSlice < m_slices - 1 ; currSlice++)
			{
				i[0] = (currStack+1)*m_slices + currSlice;
				i[1] = currStack*m_slices + currSlice;
				i[2] = i[1] + 1;
				i[3] = i[0] + 1;

				// Esto es porque son quads.
				m_indices.push_back(i[0]);
				m_indices.push_back(i[1]);
				m_indices.push_back(i[2]);
				m_indices.push_back(i[3]);
			}
		}
	}
}

void RevolutionSurface::loadVertexArray()
{
	// ESTA SUPONIENDO SIEMPRE PLANO XZ.
	vector<Point3D*>::iterator i;
	
	//La cantidad de slices debe ser mayor a cero.
	float angle,step = 360/(float)(m_slices-1);
	
	Point3D point(0,0,0);
	
	// Como estoy incluyendo el 360 para los calculos tengo un slice mas, aunque no es visible.
	//m_slices+= 1;

	for(i = m_curvePoints.begin(); i  <  m_curvePoints.end() ; i++)
	{
		// Voy obteniendo para un punto de la curva, todos los que se generan a partir de la rotacion en el eje z.
		angle = 0;
		for (int j = 0; j < m_slices ; j++, angle += step)
		{			
			point.x = (*i)->x*cosf(Mathematic::toRadians(angle));
			point.y = (*i)->x*sinf(Mathematic::toRadians(angle));
			point.z = (*i)->z;

			m_vertices.push_back(point.x);
			m_vertices.push_back(point.y);
			m_vertices.push_back(point.z);
		}
	}	
}

void RevolutionSurface::loadTextureCoordArray()
{
	////Me aseguro que la cantidad de stacks sea igual a la cantidad de puntos de la curva.
	m_stacks = m_curvePoints.size();

	float u = 0, v = 0;

	float step_u = 1.0f/(float)(m_slices - 1);
	float step_v = 1.0f/(float)(m_stacks - 1);

	if (m_stacks > 0)
	{
		v = 0;
		for (int i = 0; i < m_stacks; i++, v += step_v)
		{
			u = 0;
			for(int j = 0; j < m_slices; j ++ , u+= step_u)
			{
				m_textureCoords.push_back(u);
				m_textureCoords.push_back(v);
			}
		}
	}
}


void RevolutionSurface::loadNormalArray()
{
	// ESTA SUPONIENDO SIEMPRE PLANO XZ.
	vector<Point3D*>::iterator i;
	
	//La cantidad de slices debe ser mayor a cero.
	float angle,step = 360/(float)(m_slices-1);
	
	Point3D point(0,0,0);
	
	// Como estoy incluyendo el 360 para los calculos tengo un slice mas, aunque no es visible.
	//m_slices+= 1;

	ListPoints3D normals;

	Point3D vert1(0,0,0);
	Point3D vert2(0,0,0);
	unsigned int currVertice = 0,nextVertice = 0;

	
	for(int currentStack = 0 ; currentStack < m_stacks-1; currentStack ++)
	{
		currVertice = currentStack * m_slices*3;
		nextVertice = (currentStack+1) * m_slices*3;
		
		vert1.x = m_vertices[currVertice];
		vert1.y = m_vertices[currVertice+1];
		vert1.z = m_vertices[currVertice+2];

		vert2.x = m_vertices[nextVertice];
		vert2.y = m_vertices[nextVertice+ 1];
		vert2.z = m_vertices[nextVertice+ 2];

		normals.push_back(new Point3D((vert2-vert1).z,0,-(vert2-vert1).x));
	}
	normals.push_back(new Point3D(*normals.back()));
	

	for(i = normals.begin(); i  <  normals.end() ; i++)
	{
		// Voy obteniendo para un punto de la curva, todos los que se generan a partir de la rotacion en el eje z.
		angle = 0;
		for (int j = 0; j < m_slices ; j++, angle += step)
		{			
			point.x = (*i)->x*cosf(Mathematic::toRadians(angle));
			point.y = (*i)->x*sinf(Mathematic::toRadians(angle));
			point.z = (*i)->z;

			m_normals.push_back(point.x);
			m_normals.push_back(point.y);
			m_normals.push_back(point.z);
		}
	}
}